package com.shop.cereshop.agent.service.voucher.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shop.cereshop.agent.dao.user.CereAgentPrivateDAO;
import com.shop.cereshop.agent.dao.user.CereAgentUserDAO;
import com.shop.cereshop.agent.dao.voucher.AgentFeeStandardDAO;
import com.shop.cereshop.agent.dao.voucher.AgentVoucherUserDAO;
import com.shop.cereshop.agent.dao.wallet.AgentWalletDAO;
import com.shop.cereshop.agent.dao.wallet.AgentWalletTransactionDAO;
import com.shop.cereshop.agent.page.user.AgentUserPayVO;
import com.shop.cereshop.agent.page.user.CereAgentUserVO;
import com.shop.cereshop.agent.page.wallet.AgentWalletVO;
import com.shop.cereshop.agent.param.user.AgentUserInfoDTO;
import com.shop.cereshop.agent.param.voucher.PickVoucherDTO;
import com.shop.cereshop.agent.param.wallet.WalletPayDTO;
import com.shop.cereshop.agent.service.voucher.AgentVoucherUserService;
import com.shop.cereshop.commons.constant.CoReturnFormat;
import com.shop.cereshop.commons.constant.IntegerEnum;
import com.shop.cereshop.commons.domain.agent.CereAgentPrivate;
import com.shop.cereshop.commons.domain.agent.CereAgentVoucherUser;
import com.shop.cereshop.commons.domain.voucher.AgentFeeStandard;
import com.shop.cereshop.commons.domain.wallet.CereAgentWallet;
import com.shop.cereshop.commons.domain.wallet.CereAgentWalletTransaction;
import com.shop.cereshop.commons.exception.CoBusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 用户代金券服务实现类
 */
@Service
public class AgentVoucherUserServiceImpl extends ServiceImpl<AgentVoucherUserDAO, CereAgentVoucherUser>
    implements AgentVoucherUserService {

  @Autowired
  private CereAgentPrivateDAO CereAgentPrivateDAO;

  @Autowired
  private AgentFeeStandardDAO agentFeeStandardDAO;

  @Autowired
  private AgentWalletDAO agentWalletDAO;

  @Autowired
  private AgentWalletTransactionDAO agentWalletTransactionDAO;

  @Autowired
  private CereAgentUserDAO cereAgentUserDAO;


  @Override
  public Integer pickCity(PickVoucherDTO pickVoucherDTO) throws CoBusinessException {
    //判断当前城市是否已选择
    CereAgentPrivate agentPrivate = CereAgentPrivateDAO.selectPickCity(pickVoucherDTO.getCityCode(), pickVoucherDTO.getCityName());
    if (agentPrivate != null) {
      throw new CoBusinessException(CoReturnFormat.AGENT_CITY_PICKED);
    }
    //绑定用户和城市
    return CereAgentPrivateDAO.updateCity(pickVoucherDTO);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void buyVoucher(WalletPayDTO param, Long agentUserId) throws CoBusinessException {
    //1、根据用户id查询用户基础信息
    AgentUserPayVO user = cereAgentUserDAO.getUserInfo(new AgentUserInfoDTO(agentUserId, IntegerEnum.ROLE_TYPE_AGENT.getCode()));
    //2、需要判断用户是否设置支付密码
    //todo:和前端说需要考虑用户未设置支付密码、判断代理商是否选定城市
    if (IntegerEnum.NO.getCode().equals(user.getIsSetPayPassword())) {
        throw new CoBusinessException(CoReturnFormat.PAY_PASSWORD_NOT_SET);
    }
    //3、判断支付密码是否正确
    if (!param.getPayPassword().equals(user.getPayPassword())) {
        //增加错误次数
        user.setPayPasswordErrorCount(user.getPayPasswordErrorCount() + 1);

    }
    //4、判断代理商是否选定城市
    if (StrUtil.isBlank(user.getCityCode())) {
        throw new CoBusinessException(CoReturnFormat.AGENT_CITY_PICKED);
    }

    //5、根据代理城市code查询代金券收费标准
    LambdaQueryWrapper<AgentFeeStandard> standardWrapper = new LambdaQueryWrapper<>();
    standardWrapper.eq(AgentFeeStandard::getCityCode, user.getCityCode())
            .select(AgentFeeStandard::getAgentFee)
            .select(AgentFeeStandard::getCityCode)
            .select(AgentFeeStandard::getCityName);
    AgentFeeStandard agentFeeStandard = agentFeeStandardDAO.selectOne(standardWrapper);
    if (agentFeeStandard == null) {
      throw new CoBusinessException(CoReturnFormat.FAIL, "代金券收费标准不存在");
    }
    BigDecimal agentFee = agentFeeStandard.getAgentFee();
    //6、余额支付
    AgentWalletVO wallet = agentWalletDAO.getWallet(agentUserId, IntegerEnum.ROLE_TYPE_AGENT.getCode());
    if (wallet == null) {
      throw new CoBusinessException(CoReturnFormat.FAIL, "用户钱包不存在");
    }
    if (wallet.getBalance().compareTo(agentFee) < 0) {
      throw new CoBusinessException(CoReturnFormat.FAIL, "余额不足");
    }
    BigDecimal balance = wallet.getBalance();
    BigDecimal newBalance = balance.subtract(agentFee);
    LambdaUpdateWrapper<CereAgentWallet> walletWrapper = new LambdaUpdateWrapper<>();
    walletWrapper
            .eq(CereAgentWallet::getWalletId, wallet.getWalletId())
            .set(CereAgentWallet::getBalance, newBalance);
    int update = agentWalletDAO.update(null, walletWrapper);
    if (update <= 0) {
      throw new CoBusinessException(CoReturnFormat.FAIL, "用户余额扣减失败");
    }
    //todo:7、新增上级代理商分润
    //8、新增钱包流水
    CereAgentWalletTransaction build = CereAgentWalletTransaction.builder()
            .agentUserId(agentUserId)
            .transactionType(IntegerEnum.AGENT_TRANSACTION_TYPE_CONSUME.getCode())
            .amount(agentFee)
            .balanceBefore(balance)
            .balanceAfter(newBalance)
            .description("购买代金券")
            .createTime(LocalDateTime.now())
            .roleType(IntegerEnum.ROLE_TYPE_AGENT.getCode())
            .build();
    agentWalletTransactionDAO.insert(build);
  }
}
